//
//  CodingConvertor.swift
//  MoonKit
//
//  Created by moon on 2019/3/7.
//  Copyright © 2019 moon. All rights reserved.
//

import Foundation
public protocol CodingConvertor {
	associatedtype CodingType
	
	/// 解码coder.返回被解码出来的对象
	///
	/// - Parameter coder: 待解码的coder容器
	/// - Returns: 返回被解码出来的对象.
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.keyNotFound`: coder的codingPath对应的key不存在
	/// - Throws: `CodingError.indexOutOfRange` : coder的codingPath中的索引超过范围
	func decode(from coder: Coder) throws -> CodingType
    
    func decode(from coder: Coder,to value:inout CodingType) throws
	
	/// 解码coder.当coder容器为nil时,返回nil,否则返回被解码出来的对象
	///
	/// - Parameter coder: 待解码的coder容器
	/// - Returns: .当coder容器为nil时,返回nil,否则返回被解码出来的对象
	/// - Throws: `CodingError.typeMismatch`: 类型错误
	/// - Throws: `CodingError.keyNotFound`: coder的codingPath对应的key不存在
	/// - Throws: `CodingError.indexOutOfRange` : coder的codingPath中的索引超过范围
	func decodeIfPresent(from coder: Coder) throws -> CodingType?
	
	/// 编码值对coder容器中
	///
	/// - Parameters:
	///   - coder: 待编码的容器
	///   - value: 待编码的值
	/// - Throws: `CodingError.keyNotFound` : key不存在
	/// - Throws: `CodingError.typeMismatch` : key对应的类型不为keyed容器
	/// - Throws: `CodingError.indexOutOfRange` : 当前索引超过范围
	func encode(to coder:Coder,value: CodingType) throws
}
extension CodingConvertor {
    public func decode(from coder: Coder, to value: inout CodingType) throws {
        value = try decode(from: coder)
    }
    public func decode(from coder: Coder, to value: inout CodingType?) throws {
        if value == nil {
            value = try decode(from: coder)
        } else {
            try decode(from: coder, to: &value!)
        }
    }
	public func decodeIfPresent(from coder: Coder) throws -> CodingType? {
		if try coder.decodeNil() {
			return nil
		}
		return try decode(from: coder)
	}
}
